/*
 * Copyright (c) 2008 Open Kernel Labs, Inc. (Copyright Holder).
 * All rights reserved.
 *
 * 1. Redistribution and use of OKL4 (Software) in source and binary
 * forms, with or without modification, are permitted provided that the
 * following conditions are met:
 *
 *     (a) Redistributions of source code must retain this clause 1
 *         (including paragraphs (a), (b) and (c)), clause 2 and clause 3
 *         (Licence Terms) and the above copyright notice.
 *
 *     (b) Redistributions in binary form must reproduce the above
 *         copyright notice and the Licence Terms in the documentation and/or
 *         other materials provided with the distribution.
 *
 *     (c) Redistributions in any form must be accompanied by information on
 *         how to obtain complete source code for:
 *        (i) the Software; and
 *        (ii) all accompanying software that uses (or is intended to
 *        use) the Software whether directly or indirectly.  Such source
 *        code must:
 *        (iii) either be included in the distribution or be available
 *        for no more than the cost of distribution plus a nominal fee;
 *        and
 *        (iv) be licensed by each relevant holder of copyright under
 *        either the Licence Terms (with an appropriate copyright notice)
 *        or the terms of a licence which is approved by the Open Source
 *        Initative.  For an executable file, "complete source code"
 *        means the source code for all modules it contains and includes
 *        associated build and other files reasonably required to produce
 *        the executable.
 *
 * 2. THIS SOFTWARE IS PROVIDED ``AS IS'' AND, TO THE EXTENT PERMITTED BY
 * LAW, ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED.  WHERE ANY WARRANTY IS
 * IMPLIED AND IS PREVENTED BY LAW FROM BEING DISCLAIMED THEN TO THE
 * EXTENT PERMISSIBLE BY LAW: (A) THE WARRANTY IS READ DOWN IN FAVOUR OF
 * THE COPYRIGHT HOLDER (AND, IN THE CASE OF A PARTICIPANT, THAT
 * PARTICIPANT) AND (B) ANY LIMITATIONS PERMITTED BY LAW (INCLUDING AS TO
 * THE EXTENT OF THE WARRANTY AND THE REMEDIES AVAILABLE IN THE EVENT OF
 * BREACH) ARE DEEMED PART OF THIS LICENCE IN A FORM MOST FAVOURABLE TO
 * THE COPYRIGHT HOLDER (AND, IN THE CASE OF A PARTICIPANT, THAT
 * PARTICIPANT). IN THE LICENCE TERMS, "PARTICIPANT" INCLUDES EVERY
 * PERSON WHO HAS CONTRIBUTED TO THE SOFTWARE OR WHO HAS BEEN INVOLVED IN
 * THE DISTRIBUTION OR DISSEMINATION OF THE SOFTWARE.
 *
 * 3. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ANY OTHER PARTICIPANT BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdarg.h>

#include <fs/fs.h>

#include <iguana/env.h>
#include <iguana/memsection.h>

/*
 * #define dprintf(arg...) printf("[%s] ", __func__);printf(arg) 
 */
#define dprintf(arg...)

struct regfile {
    char file_size[16];
    void *data;
};

struct regfile test_file;
struct regfile test_file_2;

struct fdesc ftable[MAX_FILES];

int
okl4_open(const char *path, int oflag, ...)
{
    struct fdesc *f;
    int fd, r;
    int socket_vector[2];

    const envitem_t *the_file;
    memsection_ref_t file_memsec;
    struct regfile *new_file;

    /*
     * check that the file exists 
     */
    if (path == NULL) {
        errno = ENOENT;
        return -1;
    }

    if (strcmp(path, "intervm_test") == 0) {
         r = okl4_socketpair(0, SOCK_STREAM, 0, socket_vector, 1);
        if (r < 0) {
            return r;
        }

         return socket_vector[0];
    }

    if (strcmp(path, "serial") == 0) {
#ifdef __USE_POSIX
        fd = 3;
        while (ftable[fd].refcount > 0) {
            fd++;
        }
        if (fd >= MAX_FILES) {
            errno = ENFILE;
            return -1;
        }
        f = &(ftable[fd]);
        f->ftype = SERIAL;
        f->refcount++;
        f->U.s.serial = fopen("serial", "rw");
        if (f->U.s.serial == NULL) {
            f->refcount--;
            return -1;
        }
        return fd;
#else
        errno = ENXIO;
        return -1;
#endif
    }

    if (strcmp(path, "test_file") != 0 && strcmp(path, "test_file_2") != 0) {
        /*
         * check that the flags are ok 
         */
        if ((oflag & O_WRONLY) == O_WRONLY || (oflag & O_CREAT) == O_CREAT
            || (oflag & O_TRUNC) == O_TRUNC) {
            errno = EROFS;
            return -1;
        }

        the_file = iguana_getenv(path);
        if (the_file == NULL) {
            errno = ENOENT;
            return -1;
        }
        if (env_type(the_file) != ENV_MEMSECTION) {
            errno = EINVAL;
            return -1;
        }
        file_memsec = env_memsection(the_file);
        new_file = env_memsection_base(the_file);
    } else if (strcmp(path, "test_file") == 0) {
        new_file = &test_file;
    } else {
        new_file = &test_file_2;
    }

    /*
     * allocate a new file descriptor 
     */
    fd = 3;
    while (ftable[fd].refcount > 0) {
        fd++;
    }
    if (fd >= MAX_FILES) {
        errno = ENFILE;
        return -1;
    }

    f = &(ftable[fd]);
    f->size = strtol(new_file->file_size, (char **)NULL, 10);
    f->U.r.base = (uintptr_t)&(new_file->data);
    f->ftype = REGULAR;
    f->flags = oflag;
    f->refcount++;
    f->U.r.offset = 0;

    return fd;
}


